﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.IO;
using System.Configuration;
using FishWebLib;
using SGRapidForm.Common;
using ClownFish;

/// <summary>
///AppHelper 的摘要说明
/// </summary>
public static class AppHelper
{
    public static readonly int DefaultPageSize = 10;
    public static readonly int DefaultPickerPageSize = 10;

    public static readonly string AppName = "FishLib-Lab-Demo";
    public static readonly string ErrorLogFilePath = "~/App_Data/ErrorLog.txt";

    /// <summary>
    /// 应用程序初始化
    /// </summary>
    public static void Init()
    {
        ConnectionStringSettings setting = ConfigurationManager.ConnectionStrings["LocalSqlServer"];

        if (setting == null || string.IsNullOrEmpty(setting.ConnectionString))
            throw new Exception("没有设置连接字符串。");

        // 设置默认的数据库连接字符串。
        FishDbContext.Init(setting.ProviderName, "@", setting.ConnectionString);

        // 需要自动在调用存储过程后，取出将输出参数并赋值到调用对象的相关成员。
        FishDbContext.AutoGetSpOutputValues = true;

        // 判断一个对象是否可以称为“数据实体类”的判断方法。#####其实不用下面这个配置也是可以的。#####
        // 一般来说，不加这个设置也是可以的。不过，如果您的程序的所有实体是从某个类型继承过来的，
        // 就像本示例程序一样，那么使用下面的这个方法可以让FishWebLib更准确快速的识别实体类型，因此在此情形下是建议设置的。
        FishItemHelper.CheckTypeIsDataItemFunc = (x => x.IsSubclassOf(typeof(EntityBase)));

        // 设置在从数据库加载实体时，是否采用【严格】的加载模式，此时要求每个成员都能加载成功。默认值：true
        // 如果您的代码经常只需要加载实体成员的一部分成员，那么请启用下面的代码。
        FishWebLib.FishDbContext.StrictModeLoadItem = false;


        // 检查网站的BIN目录是否包含FishSQLProfilerLibrary.dll， 如果存在，则调用FishSQLProfilerLibrary.dll中的SubscribeNotify()方法
        // 只有在调用下面这个方法后，才可以运行FishSQLProfiler.exe来查看程序在运行时对数据库的访问情况。
        // 建议在调试程序时，注释下面的调用。
        //默认不适用，调试使用
        //FishDbContext.TryInvokeSubscribeNotifyInFishSQLProfilerLibraryDll();

        #region ClownFish

        // 设置配置参数：当成功执行数据库操作后，如果有输出参数，则自动获取返回值并赋值到实体对象的对应数据成员中。
        DbContextDefaultSetting.AutoRetrieveOutputValues = true;



        // 加载XmlCommand
        //string path = System.IO.Path.Combine(HttpRuntime.AppDomainAppPath, @"XmlCommand\Demo");
        //XmlCommandManager.LoadCommnads(path);

        // 注册编译失败事件，用于检查在编译实体加载器时有没有失败。
        BuildManager.OnBuildException += new BuildExceptionHandler(BuildManager_OnBuildException);

        // 开始准备向ClownFishSQLProfiler发送所有的数据库访问操作日志
        //Profiler.ApplicationName = "ClownFishDEMO";
        //Profiler.TryStartClownFishProfiler();


        // 注册SQLSERVER数据库连接字符串
        ConnectionStringSettings settingConn = ConfigurationManager.ConnectionStrings["LocalSqlServer"];
        DbContext.RegisterDbConnectionInfo("sqlserver", settingConn.ProviderName, "@", settingConn.ConnectionString);


        // 启动自动编译数据实体加载器的工作模式。
        // 编译的触发条件：请求实体加载器超过2000次，或者，等待编译的类型数量超过100次
        BuildManager.StartAutoCompile(() => BuildManager.RequestCount > 2000 || BuildManager.WaitTypesCount > 100);

        // 启动自动编译数据实体加载器的工作模式。每10秒【固定】启动一个编译过程。
        // 注意：StartAutoCompile只能调用一次，第二次调用时，会引发异常。
        //BuildManager.StartAutoCompile(() => true, 10000);

        // 手动提交要编译加载器的数据实体类型。
        // 说明：手动提交与自动编译不冲突，不论是同步还是异步。
        //Type[] models = BuildManager.FindModelTypesFromCurrentApplication(t => t.FullName.StartsWith("SGRapidForm.Demo.Entity."));
        //BuildManager.CompileModelTypesSync(models, true);
        //BuildManager.CompileModelTypesAsync(models);

        #endregion
    }

    /// <summary>
    /// 记录异常
    /// 安全地记录一个异常对象到文本文件。
    /// </summary>
    /// <param name="ex"></param>
    public static void SafeLogException(Exception ex)
    {
        if (ex is MyMessageException)
            return;

        if (ex is HttpException)
        {
            HttpException ee = ex as HttpException;
            if (ee.GetHttpCode() == 404)
                return;
        }

        // 为了避免在发布压缩包时会包含错误日志文件，这里就不记录了。

        //try {
        //    string message = string.Concat(
        //        "Request Url: ", HttpContext.Current.Request.RawUrl, "\r\n",
        //        ExecptionHelper.GetExecptionDetailInfo(ex), "\r\n\r\n\r\n");

        //    System.IO.File.AppendAllText(HttpContext.Current.Request.MapPath(ErrorLogFilePath), message, System.Text.Encoding.UTF8);
        //}
        //catch { }
    }

    static void BuildManager_OnBuildException(Exception ex)
    {
        CompileException ce = ex as CompileException;
        if (ce != null)
            SafeLogException(ce.GetDetailMessages());
        else
            SafeLogException(ex.ToString());
    }

    public static void SafeLogException(string message)
    {
        try
        {
            string logfilePath = Path.Combine(HttpRuntime.AppDomainAppPath, @"App_Data\ErrorLog.txt");

            File.AppendAllText(logfilePath, "=========================================\r\n" + message, System.Text.Encoding.UTF8);
        }
        catch { }
    }
}
